home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / dbu / ksort.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-18  |  16.7 KB  |  852 lines

  1. # include    <stdio.h>
  2. # include    <ingres.h>
  3. # include    <aux.h>
  4. # include    <symbol.h>
  5. # include    <access.h>
  6. # include     <func.h>
  7. # include    <batch.h>
  8. # include    <catalog.h>
  9. # include    <pv.h>
  10. # include    <sccs.h>
  11.  
  12. SCCSID(@(#)ksort.c    8.4    12/8/85)
  13.  
  14. # define    N    7
  15. # define    MEM    (32768 - 2)
  16. # define    BUCKETSIZE    4
  17. # define    ENDKEY    MAXDOM + 1
  18.  
  19.  
  20.  
  21. /*
  22. **    Parameters:
  23. **
  24. **        pv[0]:        Fileset
  25. **        pv[1]:        Infile from which reln is read
  26. **        pv[2]:        Outfile to which reln is written
  27. **        pv[3...]:    the desc of the new relation
  28. **
  29. **    Trace Flag:    Z37
  30. */
  31.  
  32. extern short    tTdbu[100];
  33. extern int    ksort();
  34. extern int    null_fn();
  35.  
  36. struct fn_def KsortFn =
  37. {
  38.     "KSORT",
  39.     ksort,
  40.     null_fn,
  41.     null_fn,
  42.     NULL,
  43.     0,
  44.     tTdbu,
  45.     100,
  46.     'Z',
  47.     0
  48. };
  49.  
  50. static char        *Infile;
  51. static char        *Outfile;
  52. static DESC        Desc;
  53. static char        Descsort[MAXDOM+1];
  54. static FILE        *Oiop;
  55. static int        Tupsize;
  56. static int        Bucket;
  57. static char        File[15];
  58. static char        *Fileset;
  59. static char        *Filep;
  60. static int        Nlines;
  61. static long        Ccount;
  62. static char        **Lspace;
  63. static char        *Tspace;
  64. extern int        cmpa();
  65. static long        Tupsout;
  66. static int        firstime    = 1;
  67. static FILE        *Btree_fp;
  68. DESC            Btreesec;
  69. int            Btree_fd;
  70. int            Nfiles;
  71.  
  72. ksort(pc, pv)
  73. int    pc;
  74. PARM    *pv;
  75. {
  76.     extern char    *Proc_name;
  77.     register int    i;
  78.     register int    j;
  79.     unsigned int    mem;
  80.     char        *start;
  81.     int        maxkey, rev;
  82.     extern char    *malloc();
  83.  
  84. # ifdef xZTR1
  85.     if (tTf(37,0))
  86.     {
  87.         lprintf("entering ksort\n");
  88.         prvect(pc,pv);
  89.     }
  90. # endif
  91.  
  92.     Nfiles = 1;
  93.     Fileset = pv[0].pv_val.pv_str;
  94.  
  95.     /* first, the struct relation reldum */
  96.     strcpy(Desc.reldum.relid, pv[3].pv_val.pv_str);
  97.     strcpy(Desc.reldum.relowner, pv[4].pv_val.pv_str);
  98.     Desc.reldum.relspec = pv[5].pv_val.pv_int;
  99.     Desc.reldum.relindxd = pv[6].pv_val.pv_int;
  100.     Desc.reldum.relstat2 = pv[7].pv_val.pv_int;
  101.     Desc.reldum.relstat = pv[8].pv_val.pv_int;
  102.     Desc.reldum.relsave = (long) pv[9].pv_val.pv_int;
  103.     Desc.reldum.reltups = (long) pv[10].pv_val.pv_int;
  104.     Desc.reldum.relatts = pv[11].pv_val.pv_int;
  105.     Desc.reldum.relwid = pv[12].pv_val.pv_int;
  106.     Desc.reldum.relprim = (long) pv[13].pv_val.pv_int;
  107.     Desc.reldum.relfree = (long) pv[14].pv_val.pv_int;
  108.     Desc.reldum.relstamp = (long) pv[15].pv_val.pv_int;
  109.     Desc.reldum.reldim = pv[16].pv_val.pv_int;
  110.  
  111.     strcpy(Desc.relvname, pv[17].pv_val.pv_str);
  112.     Desc.relfp = pv[18].pv_val.pv_int;
  113.     Desc.relopn = pv[19].pv_val.pv_int;
  114.     Desc.reladds = (long) pv[20].pv_val.pv_int;
  115.     Desc.reltid.ltid = pv[21].pv_val.pv_int;
  116.     j = 22;
  117.     for (i = 0; i <= Desc.reldum.relatts; ++i)
  118.     {
  119.         Desc.reloff[i] = pv[j++].pv_val.pv_int;
  120.         Desc.relfrmt[i] = pv[j++].pv_val.pv_int;
  121.         Desc.relfrml[i] = pv[j++].pv_val.pv_int;
  122.         Desc.relxtra[i] = pv[j++].pv_val.pv_int;
  123.         Desc.relgiven[i] = pv[j++].pv_val.pv_int;
  124.     }
  125.  
  126.     if (Desc.reldum.reldim > 0)
  127.     {
  128.         if ((Desc.relbtree = (DESC *) calloc(1, sizeof(DESC))) == NULL)
  129.             syserr("bad calloc in ksort");
  130.         /* first, the struct relation reldum */
  131.         strcpy(Desc.relbtree->reldum.relid, pv[j++].pv_val.pv_str);
  132.         strcpy(Desc.relbtree->reldum.relowner, pv[j++].pv_val.pv_str);
  133.         Desc.relbtree->reldum.relspec = pv[j++].pv_val.pv_int;
  134.         Desc.relbtree->reldum.relindxd = pv[j++].pv_val.pv_int;
  135.         Desc.relbtree->reldum.relstat2 = pv[j++].pv_val.pv_int;
  136.         Desc.relbtree->reldum.relstat = pv[j++].pv_val.pv_int;
  137.         Desc.relbtree->reldum.relsave = pv[j++].pv_val.pv_int;
  138.         Desc.relbtree->reldum.reltups = pv[j++].pv_val.pv_int;
  139.         Desc.relbtree->reldum.relatts = pv[j++].pv_val.pv_int;
  140.         Desc.relbtree->reldum.relwid = pv[j++].pv_val.pv_int;
  141.         Desc.relbtree->reldum.relprim = pv[j++].pv_val.pv_int;
  142.         Desc.relbtree->reldum.relfree = pv[j++].pv_val.pv_int;
  143.         Desc.relbtree->reldum.relstamp = pv[j++].pv_val.pv_int;
  144.         Desc.relbtree->reldum.reldim = pv[j++].pv_val.pv_int;
  145.  
  146.         strcpy(Desc.relbtree->relvname, pv[j++].pv_val.pv_str);
  147.         Desc.relbtree->relfp = pv[j++].pv_val.pv_int;
  148.         Desc.relbtree->relopn = pv[j++].pv_val.pv_int;
  149.         Desc.relbtree->reladds = pv[j++].pv_val.pv_int;
  150.         Desc.relbtree->reltid.ltid = pv[j++].pv_val.pv_int;
  151.  
  152.         for (i = 0; i <= Desc.relbtree->reldum.relatts; ++i)
  153.         {
  154.             Desc.relbtree->reloff[i] = pv[j++].pv_val.pv_int;
  155.             Desc.relbtree->relfrmt[i] = pv[j++].pv_val.pv_int;
  156.             Desc.relbtree->relfrml[i] = pv[j++].pv_val.pv_int;
  157.             Desc.relbtree->relxtra[i] = pv[j++].pv_val.pv_int;
  158.             Desc.relbtree->relgiven[i] = pv[j++].pv_val.pv_int;
  159.         }
  160.     }
  161.  
  162. # ifdef xZTR1
  163.     if (tTf(37,0))
  164.     {
  165.         lprintf(" Desc read in \n");
  166.         printdesc(&Desc);
  167.     }
  168. #endif
  169.  
  170.     /* set up Descsort to indicate the sort order for tuple */
  171.     /* if domain zero is given prepare to generate "hash bucket"
  172.     ** value for tuple */
  173.  
  174.     maxkey = 0;
  175.     for (i = 0; i <= Desc.reldum.relatts; i++)
  176.         if (j = Desc.relgiven[i])
  177.         {
  178.             if ((rev = j) < 0)
  179.                 j = -j;
  180.             if (maxkey < j)
  181.                 maxkey = j;
  182.             Descsort[--j] = rev < 0 ? -i : i;
  183.         }
  184.  
  185.     Descsort[maxkey] = ENDKEY;    /* mark end of list */
  186.  
  187.     Tupsize = Desc.reldum.relwid;
  188.  
  189.     if (Bucket = (Descsort[0] == 0))
  190.     {
  191.         /* we will be generating hash bucket */
  192.         Tupsize += BUCKETSIZE;
  193.         Desc.relfrml[0] = BUCKETSIZE;
  194.         Desc.relfrmt[0] = INT;
  195.         Desc.reloff[0] = Desc.reldum.relwid;
  196.     }
  197.  
  198. # ifdef xZTR1
  199.     if (tTf(37,0))
  200.     {
  201.         lprintf("ksort: reldum.relatts is %d\n", Desc.reldum.relatts);
  202.         lprintf("Bucket is %d,Sort is:\n", Bucket);
  203.         for (i = 0; (j = Descsort[i]) != ENDKEY; i++)
  204.             lprintf("Descsort[%d]=%d\n", i, j);
  205.     }
  206. # endif
  207.     if (i = (maxkey - Bucket - Desc.reldum.relatts))
  208.     {
  209.         lprintf("MAXKEY=%d\n", maxkey);
  210.         lprintf("ATTS=%d\n", Desc.reldum.relatts);
  211.         syserr("%d domains missing\n", -i);
  212.     }
  213.     Infile = pv[1].pv_val.pv_str;
  214.     Outfile = pv[2].pv_val.pv_str;
  215.  
  216.     /* get up to 2**15 - 1 bytes of memory for buffers */
  217.     /* note that mem must end up positive so that Nlines computation is right */
  218.     mem = MEM;    /* take at most 2**15 - 1 bytes */
  219.     if (firstime)
  220.     {
  221.         while ((Lspace = (char **) malloc(mem)) == NULL)
  222.             mem -= 1024;
  223.         firstime = 0;
  224.     }
  225.  
  226.     /* compute pointers and sizes into buffer memory */
  227.     Nlines = mem / (Tupsize + sizeof(char *));
  228.     Tspace = (char *) (Lspace + Nlines);
  229. # ifdef xZTR1
  230.     if (tTf(37,0))
  231.         lprintf("Tspace=%x,Lspace=%x,Nlines=%x,mem=%d\n",
  232.             Tspace, Lspace, Nlines, mem);
  233. # endif
  234.  
  235.     /* set up temp files */
  236.     concat(ztack("_SYSS", Fileset), "Xaa", File);
  237.     Filep = File;
  238.     while (*Filep != 'X')
  239.         Filep++;
  240.     Filep++;
  241.  
  242.     if (abs(Desc.reldum.relspec) == M_ORDER)
  243.         if ((Btree_fp = fopen(Infile, "r")) == NULL)
  244.             syserr("can't open %s", Infile);
  245.  
  246.     /* sort stage -- create a bunch of temporaries */
  247.     Ccount = 0;
  248. # ifdef xZTR1
  249.     if (tTf(37,0))
  250.         lprintf("sorting\n");
  251. # endif
  252.     sort();
  253. # ifdef xZTR1
  254.     if (tTf(37,0))
  255.     {
  256.         lprintf("done sorting\n%ld tuples written to %d files\n", Tupsout, Nfiles - 1);
  257.         lprintf("sort required %ld compares\n", Ccount);
  258.     }
  259. # endif
  260.  
  261.     /* merge stage -- merge up to N temps into a new temp */
  262.     Ccount = 0;
  263.     for (i = 1; i + N < Nfiles; i += N) 
  264.     {
  265.         newfile();
  266.         merge(i, i + N);
  267.     }
  268.  
  269.     /* merge last set of temps into target file */
  270.     if (i != Nfiles) 
  271.     {
  272.         oldfile();
  273.         merge(i, Nfiles);
  274.     }
  275. # ifdef xZTR1
  276.     if (tTf(37,0))
  277.     {
  278.         lprintf("%ld tuples in out file\n", Tupsout);
  279.         lprintf("merge required %ld compares\n", Ccount);
  280.     }
  281. # endif
  282.     term(0);
  283. }
  284. /*
  285. **  SORT
  286. */
  287.  
  288. sort()
  289. {
  290.     register char    *cp;
  291.     register char    **lp;
  292.     register int    i;
  293.     int        done;
  294.     long        ntups;
  295.     struct tup_id    tid, ltid;
  296.     char        *xp;
  297.     long        pageid;
  298.     long        rhash();
  299.     char        btree[MAXNAME + 4], btreefile[MAXNAME + 4];
  300.     char        relfile[MAXNAME + 4], btreestruct[MAXNAME + 4];
  301.  
  302.     done = 0;
  303.     ntups = 0;
  304.     Tupsout = 0;
  305.     if (abs(Desc.reldum.relspec) != M_ORDER)
  306.     {
  307.         if ((Desc.relfp = open(Infile, O_RDONLY)) < 0)
  308.             cant(Infile);
  309.         Desc.relopn = (Desc.relfp + 1) * 5;
  310.     }
  311.     if (Desc.reldum.reldim > 0 && abs(Desc.reldum.relspec != M_ORDER))
  312.     /* open all needed btree files */
  313.     {
  314.         capital(Desc.reldum.relid, btree);
  315.         ingresname(btree, Desc.reldum.relowner, btreefile);
  316.         if ((Desc.relbtree->relfp = open(btreefile, O_RDONLY)) < 0)
  317.             cant(btreefile);
  318.         Desc.relbtree->relopn = (Desc.relbtree->relfp + 1) * 5;
  319.         ingresname(Desc.reldum.relid, Desc.reldum.relowner, relfile);
  320.         btreename(relfile, btreestruct);
  321.         if ((Desc.btree_fd = open(btreestruct, O_RDWR)) < 0)
  322.             cant(btreestruct);
  323.     }
  324.  
  325.     /* initialize tids for full scan */
  326.     pageid = 0;
  327.     tid.line_id = -1;
  328.     stuff_page(&tid, &pageid);
  329.     pageid = -1;
  330.     ltid.line_id = -1;
  331.     stuff_page(<id, &pageid);
  332.  
  333.     do 
  334.     {
  335.         cp = Tspace;
  336.         lp = Lspace;
  337.         while (lp < Lspace + Nlines)
  338.         {
  339.             if (abs(Desc.reldum.relspec) == M_ORDER)
  340.             {
  341.                 /* not reading from a relation */
  342.                 if ((i = fread(cp, 1, Desc.reldum.relwid, Btree_fp)) != Desc.reldum.relwid)
  343.                 {
  344.                     if (i != 0)
  345.                         syserr("read error %d", i);
  346.                     fclose(Btree_fp);
  347.                     done++;
  348.                     break;
  349.                 }
  350.             }
  351.             else if ((i = kget(&Desc, &tid, <id, cp, TRUE)) != 0)
  352.             {
  353.                 if (i < 0)
  354.                     syserr("get %d", i);
  355.                 close(Desc.relfp);
  356.                 Desc.relopn = 0;
  357.                 done++;
  358.                 break;
  359.             }
  360. # ifdef xZTR1
  361.             if (tTf(37,0))
  362.                 printup(&Desc, cp);
  363. # endif
  364.             if (Bucket)
  365.             {
  366.                 /* compute hash bucket and insert at end */
  367.                 pageid = rhash(&Desc, cp);
  368.                 bmove(&pageid, cp + Desc.reldum.relwid, BUCKETSIZE);
  369.             }
  370.             *lp++ = cp;
  371.             cp += Tupsize;
  372.             ntups++;
  373.         }
  374.         qsort(Lspace, lp - Lspace, sizeof(char *), cmpa);
  375.         if (done == 0 || Nfiles != 1)
  376.             newfile();
  377.         else
  378.             oldfile();
  379.         while (lp > Lspace) 
  380.         {
  381.             cp = *--lp;
  382.             xp = cp;
  383.             if ((lp == Lspace) || (i = abs(cmpa(&xp, &lp[-1]))) != 0 || (i == 0 && abs(Desc.reldum.relspec) == M_ORDER))
  384.             {
  385. # ifdef xZTR1
  386.                 if (tTf(37,0))
  387.                 {
  388.                     lprintf("writing ");
  389.                     printup(&Desc, cp);
  390.                 }
  391. # endif
  392.                 if ((i = fwrite(cp, 1, Tupsize, Oiop)) != Tupsize)
  393.                     syserr("cant write outfile %d (%d)", i, Nfiles);
  394.                 Tupsout++;
  395.             }
  396.         }
  397.         fclose(Oiop);
  398.     } while (done == 0);
  399.     if (Desc.reldum.reldim > 0 && Desc.reldum.relspec != M_ORDER)
  400.     {
  401.         close(Desc.relbtree->relfp);
  402.         Desc.relbtree->relopn = 0;
  403.         close(Desc.btree_fd);
  404.     }
  405. # ifdef xZTR1
  406.     if (tTf(37,0))
  407.         lprintf("%ld tuples in\n", ntups);
  408. # endif
  409. }
  410. /*
  411. **  MERGE
  412. */
  413.  
  414. struct merg
  415. {
  416.     char        tup[MAXTUP+BUCKETSIZE];
  417.     int        filedes;
  418.     FILE        *fiop;
  419. };
  420.  
  421. merge(a, b)
  422. int    a;
  423. int    b;
  424. {
  425.     register struct merg    *merg;
  426.     register int        i, j;
  427.     char            *f, *yesno;
  428.     struct merg        *mbuf[N + 1];
  429.     char            *setfil();
  430.  
  431. # ifdef xZTR1
  432.     if (tTf(37,0))
  433.         lprintf("merge %d to %d\n", a, b);
  434. # endif
  435.     merg = (struct merg *) Lspace;
  436.     j = 0;
  437.     for (i = a; i < b; i++) 
  438.     {
  439.         f = setfil(i);
  440.         mbuf[j] = merg;
  441.         merg->filedes = i;
  442.         if ((merg->fiop = fopen(f, "r")) == NULL)
  443.             cant(f);
  444.         if (!rline(merg))
  445.             j++;
  446.         merg++;
  447.     }
  448.  
  449.     i = j - 1;
  450. # ifdef xZTR1
  451.     if (tTf(37,0))
  452.         lprintf("start merg with %d\n", i);
  453. # endif
  454.     while (i >= 0) 
  455.     {
  456. # ifdef xZTR1
  457.         if (tTf(37,0))
  458.             lprintf("mintup %d\n", i);
  459. # endif
  460.         if (mintup(mbuf, i, cmpa))
  461.         {
  462.             if (fwrite(mbuf[i]->tup, 1, Tupsize, Oiop) != Tupsize)
  463.                 syserr("cant write merge output");
  464.             Tupsout++;
  465.         }
  466.         merg = mbuf[i];
  467.         if (rline(merg))
  468.         {
  469.             yesno = "not ";
  470. # ifdef xZTR1
  471.             if (!tTf(37,0))
  472.             {
  473.                 /* truncate temporary files to zero length */
  474.                 yesno = "";
  475.                 close(creat(setfil(merg->filedes), 0600));
  476.             }
  477. # endif
  478. # ifdef xZTR1
  479.             if (tTf(37,0))
  480.                 lprintf("dropping and %struncating %s\n", yesno, setfil(merg->filedes));
  481. # endif
  482.             i--;
  483.         }
  484.     }
  485.  
  486.     fclose(Oiop);
  487. }
  488. /*
  489. **    Mintup puts the smallest tuple in mbuf[cnt-1].
  490. **    If the tuple is a duplicate of another then
  491. **    mintup returns 0, else 1.
  492. **
  493. **    Cnt is the number of compares to make; i.e.
  494. **    mbuf[cnt] is the last element.
  495. */
  496.  
  497. mintup(mbuf, cnt, cmpfunc)
  498. struct merg    *mbuf[];
  499. int        cnt;
  500. int        (*cmpfunc)();
  501. {
  502.     register struct merg    **next, **last;
  503.     struct merg        *temp;
  504.     register int        nodup;
  505.     int            j;
  506.  
  507.     nodup = TRUE;
  508.     next = mbuf;
  509.     last = &next[cnt];
  510.  
  511.     while (cnt--)
  512.     {
  513.         if (j = (*cmpfunc)(last, next))
  514.         {
  515.             /* tuples not equal. keep smallest */
  516.             if (j < 0)
  517.             {
  518.                 /* exchange */
  519.                 temp = *last;
  520.                 *last = *next;
  521.                 *next = temp;
  522.                 nodup = TRUE;
  523.             }
  524.         }
  525.         else
  526.             nodup = FALSE;
  527.  
  528.         next++;
  529.     }
  530.     return (nodup);
  531. }
  532.  
  533. char *setfil();
  534.  
  535. rline(mp)
  536. struct merg    *mp;
  537. {
  538.     register struct merg    *merg;
  539.     register int        i;
  540.  
  541.     merg = mp;
  542.     if ((i = fread(merg->tup, 1, Tupsize, merg->fiop)) != Tupsize)
  543.     {
  544.         if (i == 0)
  545.         {
  546.             fclose(merg->fiop);
  547.             return (1);
  548.         }
  549.         syserr("rd err %d on %s", i, setfil(merg->filedes));
  550.     }
  551.     return (0);
  552. }
  553.  
  554. newfile()
  555. {
  556.  
  557.     makfile(setfil(Nfiles));
  558.     Nfiles++;
  559. }
  560. /*
  561. **    Convert the number i to a char
  562. **    sequence aa, ab, ..., az, ba, etc.
  563. */
  564.  
  565. char *
  566. setfil(i)
  567. int    i;
  568. {
  569.     register int    j;
  570.  
  571.     j = i;
  572.     j--;
  573.     Filep[0] = j/26 + 'a';
  574.     Filep[1] = j%26 + 'a';
  575.     return (File);
  576. }
  577.  
  578. oldfile()
  579. {
  580.     makfile(Outfile);
  581.     Tupsout = 0;
  582. }
  583. /*
  584. **    Create a file by the name "name"
  585. **    and place its fio pointer in Oiop
  586. */
  587.  
  588. makfile(name)
  589. char    *name;
  590. {
  591.     if ((Oiop = fopen(name, "w")) == NULL)
  592.         cant(name);
  593. }
  594.  
  595. cant(f)
  596. char    *f;
  597. {
  598.     syserr("open %s", f);
  599. }
  600.  
  601. term(error)
  602. int    error;
  603. {
  604.     register int    i;
  605.  
  606.     if (Nfiles == 1)
  607.         Nfiles++;
  608. # ifdef xZTR1
  609.     if (tTf(37,0))
  610.         lprintf("temp files not removed\n");
  611.     else
  612. # endif
  613.         for (i = 1; i < Nfiles; i++) 
  614.         {
  615.             unlink(setfil(i));
  616.         }
  617.     return(error);
  618. }
  619. /*
  620. **  CMPA -- compare tuples
  621. */
  622.  
  623. cmpa(a, b)
  624. char    **a;
  625. char    **b;
  626. {
  627.     int            af[4];
  628.     int            bf[4];
  629.     char            *pa, *pb;
  630.     register union anytype    *tupa, *tupb;
  631.     int            dom;
  632.     register int        frml;
  633.     int            frmt;
  634.     int            off;
  635.     int            temp;
  636.     int            rt;
  637.     char            *dp;
  638.  
  639.     pa = *a;
  640.     pb = *b;
  641.     Ccount++;
  642.     dp = Descsort;
  643.     while ((temp = *dp++) != ENDKEY)
  644.     {
  645.         if ((dom = temp) < 0)
  646.             dom = -temp;
  647.         frml = Desc.relfrml[dom];
  648.         frmt = Desc.relfrmt[dom];
  649.         off = Desc.reloff[dom];
  650.         tupa = (union anytype *) &pa[off];
  651.         tupb = (union anytype *) &pb[off];
  652.         if (temp < 0)
  653.         {
  654.             tupb = tupa;
  655.             tupa = (union anytype *) &pb[off];
  656.         }
  657.         if (frmt == CHAR)
  658.         {
  659.             frml &= I1MASK;
  660.             if (rt = scompare(tupb, frml, tupa, frml))
  661.                 return (rt);
  662.             continue;
  663.         }
  664.  
  665.         /* domain is a numeric type */
  666.         if (bequal(tupa, tupb, frml))
  667.             continue;
  668.         /* copy to even word boundary */
  669.         bmove(tupa, af, frml);
  670.         bmove(tupb, bf, frml);
  671.         tupa = (union anytype *) af;
  672.         tupb = (union anytype *) bf;
  673.  
  674.         switch (frmt)
  675.         {
  676.  
  677.           case INT:
  678.             switch (frml)
  679.             {
  680.  
  681.               case 1:
  682.                 return (tupa->i1type > tupb->i1type ? -1 : 1);
  683.  
  684.               case 2:
  685.                 return (tupa->i2type > tupb->i2type ? -1 : 1);
  686.  
  687.               case 4:
  688.                 return (tupa->i4type > tupb->i4type ? -1 : 1);
  689.             }
  690.  
  691.           case FLOAT:
  692.             switch (frml)
  693.             {
  694.  
  695.               case 4:
  696.                 return (tupa->f4type > tupb->f4type ? -1 : 1);
  697.  
  698.               case 8:
  699.                 return (tupa->f8type > tupb->f8type ? -1 : 1);
  700.             }
  701.         }
  702.     }
  703.     return (0);
  704. }
  705. /*
  706. **    KGET_PAGE
  707. **    Replacement for access method routine get_page();
  708. **    and associated globals and routines.
  709. */
  710.  
  711. long        Accuread, Accuwrite;
  712.  
  713. kget_page(d, tid)
  714. register DESC    *d;
  715. struct tup_id    *tid;
  716. {
  717.     register int        i;
  718.     long            pageid;
  719.     register struct accbuf    *b;
  720.     extern struct accbuf    *choose_buf();
  721.  
  722. # ifdef xZTR1
  723.     if (tTf(37,0))
  724.     {
  725.         lprintf("kget_page: %.14s,", d->reldum.relid);
  726.         dumptid(tid);
  727.     }
  728. # endif
  729.     pluck_page(tid, &pageid);
  730.     if ((b = choose_buf(d, pageid)) == NULL)
  731.     {
  732. # ifdef xZTR1
  733.         if (tTf(37,0))
  734.             lprintf(" choose_buf: buffer not avail \n");
  735. # endif
  736.         return(-1);
  737.     }
  738.     top_acc(b);
  739.  
  740.     i = 0;
  741.     if (b->thispage != pageid)
  742.     {
  743. # ifdef xZTR1
  744.         if (tTf(37,0))
  745.             lprintf("kget_page: rdg pg %ld\n", pageid);
  746. # endif
  747.         b->thispage = pageid;
  748.         if ((lseek(d->relfp, pageid * PGSIZE, 0) < 0) ||
  749.             ((read(d->relfp, b, PGSIZE)) != PGSIZE))
  750.         {
  751.             i = AMREAD_ERR;
  752.         }
  753.         Accuread++;
  754.     }
  755.     return (i);
  756. }
  757.  
  758. /*
  759. **  KGET - get a single tuple
  760. **
  761. **    Get either gets the next sequencial tuple after
  762. **    "tid" or else gets the tuple specified by tid.
  763. **
  764. **    If getnxt == TRUE, then tid is incremented to the next
  765. **    tuple after tid. If there are no more, then get returns
  766. **    1. Otherwise get returns 0 and "tid" is set to the tid of
  767. **    the returned tuple.
  768. **
  769. **    Under getnxt mode, the previous page is reset before
  770. **    the next page is read. This is done to prevent the previous
  771. **    page from hanging around in the am's buffers when we "know"
  772. **    that it will not be referenced again.
  773. **
  774. **    If getnxt == FALSE then the tuple specified by tid is
  775. **    returned. If the tuple was deleted previously,
  776. **    get retuns 2 else get returns 0.
  777. **
  778. **    If getnxt is true, limtid holds the the page number
  779. **    of the first page past the end point. Limtid and the
  780. **    initial value of tid are set by calls to FIND.
  781. **
  782. **    returns:
  783. **        <0  fatal error
  784. **        0   success
  785. **        1   end of scan (getnxt=TRUE only)
  786. **        2   tuple deleted (getnxt=FALSE only)
  787. */
  788.  
  789.  
  790. kget(d, tid, limtid, tuple, getnxt)
  791. register DESC    *d;
  792. register TID    *tid;
  793. TID        *limtid;
  794. int        getnxt;
  795. char        *tuple;
  796. {
  797.     register int    i;
  798.     long        pageid, lpageid;
  799.  
  800. #    ifdef xATR1
  801.     if (tTf(23, 0) || tTf(37,0))
  802.     {
  803.         lprintf("kget: %.14s,", d->reldum.relid);
  804.         dumptid(tid);
  805.         lprintf("kget: lim");
  806.         dumptid(limtid);
  807.     }
  808. #    endif
  809.     if (kget_page(d, tid))
  810.     {
  811.         return (-1);
  812.     }
  813.     if (getnxt)
  814.     {
  815.         pluck_page(limtid, &lpageid);
  816.         do
  817.         {
  818.             while (((++(tid->line_id)) & I1MASK) >= Acc_head->nxtlino)
  819.             {
  820.                 tid->line_id = -1;
  821.                 pageid = Acc_head->ovflopg;
  822.                 stuff_page(tid, &pageid);
  823.                 if (pageid == 0)
  824.                 {
  825.                     pageid = Acc_head->mainpg;
  826.                     stuff_page(tid, &pageid);
  827.                     if (pageid == 0 || pageid == lpageid + 1)
  828.                         return (1);
  829.                 }
  830.                 if (i = resetacc(Acc_head))
  831.                     return (i);
  832.                 if (i = get_page(d, tid))
  833.                     return (i);
  834.             }
  835.         } while (!Acc_head->linetab[-(tid->line_id & I1MASK)]);
  836.     }
  837.     else
  838.     {
  839.         if (i = invalid(tid))
  840.             return (i);
  841.     }
  842.     get_tuple(d, tid, tuple);
  843. #    ifdef xATR2
  844.     if (tTf(23, 1) || tTf(37,0))
  845.     {
  846.         printf("kget: ");
  847.         printup(d, tuple);
  848.     }
  849. #    endif
  850.     return (0);
  851. }
  852.